Altering the semantics of a JVM compliant computer program via bytecode transformation is a well-known practice. Bytecode transformation has been used for many purposes, especially to enhance programs with new capabilities and or add monitoring or profiling. A widespread objective when applying bytecode transformation is full bytecode coverage of the bytecode being executed in the JVM, meaning that every class loaded into or as part of the JVM should be intercepted by the bytecode transformer to permit bytecode modifications. In contrast, incomplete bytecode coverage would cause a lack of bytecode enhancement for parts of the program that depends on modifications of parts which cannot be changed by current available techniques. Currently, many available techniques for bytecode transformation are limited in their support for full bytecode coverage. Firstly, certain core classes (the special bootstrap classes) of the JDK are completely excluded from instrumentation because they are loaded before bytecode transformation can take place. Consequently, the bytecode executed within these classes corresponds to the unmodified versions of the classes. Secondly, because of the first cause, transformation of boot-classes has to be performed statically meaning the whole method has to be transformed prior to execution.
The JDK 1.5 has introduced a mechanism, Java language instrumentation agents (package java.lang.instrument), to transform classes as they are being loaded. Even though instrumentation agents are loaded and executed before the class containing the main(String[ ]) method, these agents are loaded only after the JVM has completed bootstrapping. At this stage of the execution, already several hundred classes have been loaded but have not been processed by any instrumentation agent. The JDK offers a mechanism to redefine these pre-loaded classes, which however imposes several strong limitations on class redefinition, as summarized in the JDK 1.6 API documentation: ‘The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.’ These limitations are far too restrictive for many instrumentation-processes, such as calling context reification, which requires the introduction of additional method arguments and therefore changes method signatures. The present invention does not suffer from these strong limitations as it enables full modification of already loaded bootstrap classes.
In [1] Binder et al. discloses the method FERRARI as a general-purpose bytecode instrumentation framework. In FERRARI it's possible to instrument all classes including the special JVM bootstrap classes. However, the method requires the bytecode modifications of the JVM bootstrap classes to be done by a special static transformation tool called FIRST. Hence, FERRARI requires users to accept a two-step process in which the application is first prepared to execute, and then the real execution can be carried out. Not only does this alter the standard usage pattern of executing Java programs, but more importantly it requires the user to remember to execute the preparation tool.